package com.eryos.android.cigarettecounter;

import java.util.TreeSet;

import android.app.Activity;
import android.app.ProgressDialog;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.os.Handler;
import android.util.Log;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.widget.LinearLayout;
import android.widget.Toast;

import com.eryos.android.cigarettecounter.beans.History;
import com.eryos.android.cigarettecounter.database.CigaretteDatabase;
import com.eryos.android.cigarettecounter.tool.GoogleAnalyticsProvider;
import com.eryos.android.cigarettecounter.ui.Credits;
import com.google.ads.AdRequest;
import com.google.ads.AdSize;
import com.google.ads.AdView;

/**
 * Project : CigaretteCounter Author : Olivier Combe URL : http://eryos.fr/CigaretteCounter/
 * 
 * Copyright(C)2011 - Olivier Combe
 * 
 * Licensed under the Apache License, Version 2.0(the "License"); you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 * 
 * http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
 * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
 * specific language governing permissions and limitations under the License.
 * 
 * @version \$Revision.*\$
 * @author Olivier Combe
 */
public abstract class RootActivity extends Activity {

    /** *************** Static Variables. *************** **/
    protected String LOG_TAG = "RootActivity";

    /** Config filename. */
    public static final String PREFS_NAME = "eryos-config";
    /** Output filename. */
    public static final String SDCARD_NAME = "cigarettecounter.csv";

    /** Current database. */
    protected static CigaretteDatabase db;

    /** Ads ID. */
    private static final String MY_AD_UNIT_ID = "a14d256d9745ea0";

    private AdView adView; // = new AdView(this, AdSize.BANNER, MY_AD_UNIT_ID);

    private static CigaretteCounter home;
    private static ProgressDialog waitingDialog;
    private static View rootView = null;

    /** *************** Instance Variables. *************** **/
    protected Menu menu;

    /**
     * Different types of Historical.
     */
    public enum HISTO {
        /** Weekly histo. */
        WEEKLY,
        /** Monthly Histo. */
        MONTHLY
    };

    /**
     * List of views in the application.
     */
    public enum VIEW {
        /** Home page. */
        HOME,
        /** Weekly charts page. */
        WEEKLY,
        /** Monthly charts page. */
        MONTHLY,
        /** Settings page. */
        SETTINGS,
        /** Credits page. */
        CREDITS
    };

    private final Handler mHandler = new Handler();

    private final Runnable initValuesComplete = new Runnable() {
        @Override
        public void run() {
            /* Update the UI with values retrieved/calculated by initValues() */
            updateUI();

            /* dismiss the splash screen created after initUI() */
            hideWaitingMessageAfterLoad();
        }
    };

    /**
     * @return the default LOG_TAG.
     */
    protected String getLogTag() {
        return LOG_TAG;
    }

    /**
     * Hide the 'Waiting' popup.
     */
    public void hideWaitingMessageAfterLoad() {
        Log.d(LOG_TAG, "hideWaitingMessageAfterLoad");
        hideWaitingMessage();
    }

    /** *************** *********** *************** **/

    /**
     * {@inheritDoc}
     */
    @Override
    public void onCreate(final Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        LOG_TAG = getLocalClassName();
        Log.d(LOG_TAG, "onCreate");

        if (this instanceof CigaretteCounter) {
            if (rootView == null) {
                rootView = getWindow().getDecorView();
            }
            if (home != null) {
                home.finish();
            } else {
                // 1ere ouverture de Home
                Log.i(LOG_TAG, "######################################################");
                Log.i(LOG_TAG, "Start Eryos - CigaretteCounter");
                Log.i(LOG_TAG, "App Version : " + getResources().getString(R.string.version));
                Log.i(LOG_TAG, "App Build : " + getResources().getString(R.string.build));
                Log.i(LOG_TAG, "######################################################");
            }

            home = (CigaretteCounter) this;
        }

        /* Init UI elements */
        initUI();

        /* show splashscreen during complex treatment */
        showWaitingMessage();

        /* Init Ads */
        // initAds();

        /* Init Analytics Tracker */
        // initTracker();

        /* Init and open the DB connection */
        initDB();

        /* Init UI Handlers */
        initHandlers();

        /* Process long/complex treatments in separate thread */
        Thread t = new Thread() {
            @Override
            public void run() {
                /* Init values(from DB, Network, etc.) */
                initValues();

                /* stop this thread and return to the main thread */
                mHandler.post(initValuesComplete);
            }
        };
        t.start();

    }

    /**
     * Method used to initialize the DB connection.
     */
    private void initDB() {
        if (db == null) {
            db = CigaretteDatabase.getInstance(this);
            db.open();
        }
    }

    /**
     * Method used to handle Ads part.
     */
    private void initAds() {
        boolean showAd = true;

        if (showAd) {
            Log.i(LOG_TAG, "AdMob Initializing");
            adView = getAdView(this);

            // Lookup your LinearLayout
            LinearLayout layout;
            try {
                layout = (LinearLayout) findViewById(R.id.main_layout);

                // Add the adView to it
                layout.addView(adView);
            } catch (Exception e) {
                Log.e(LOG_TAG, "initAds", e);
            }

        }
    }

    /**
     * Get the Ad View.
     * 
     * @param activityArg
     *            which request the add.
     * @return an ad.
     */
    public static AdView getAdView(final Activity activityArg) {
        Log.i("AdView", "AdView Initializing");
        Activity activity = activityArg;

        if (activity == null) {
            Log.w("AdView", "Null Activity, using root Activity");

            activity = home;
        }
        if (activity != null) {
            // Create the adView
            AdView newAdView = new AdView(activity, AdSize.BANNER, MY_AD_UNIT_ID);

            // To get test ads on this device, call
            AdRequest adRequest = new AdRequest();
            adRequest.addTestDevice(AdRequest.TEST_EMULATOR);
            // adRequest.setLocation(location);
            TreeSet<String> keywords = new TreeSet<String>();
            keywords.add("smoke");
            keywords.add("geek");
            keywords.add("cigarette");
            keywords.add("smoking");
            adRequest.setKeywords(keywords);

            // Initiate a generic request to load it with an ad
            newAdView.loadAd(adRequest);

            Log.d("AdView", "Ad found !!!");
            return newAdView;
        }

        Log.w("AdView", "Null Activity passed in param");
        return null;
    }

    /**
     * Method used to handle Tracker.
     */
    private void initTracker() {
        Log.i(LOG_TAG, "GoogleAnalytics : Init Tracker");
        GoogleAnalyticsProvider.startTracker(this);
        GoogleAnalyticsProvider.trackCustomVars();
        GoogleAnalyticsProvider.trackPage(LOG_TAG);
        GoogleAnalyticsProvider.dispatch();
    }

    /**
     * Init all UI elements.
     */
    protected abstract void initUI();

    /**
     * Method used to defined all UI handlers.
     */
    protected abstract void initHandlers();

    /**
     * init Values(not UI)for this activiry from DB / Network / etc.
     */
    protected abstract void initValues();

    /**
     * Method used to update the UI after called to initValues().
     */
    public abstract void updateUI();

    /**
     * {@inheritDoc}
     */
    @Override
    public boolean onCreateOptionsMenu(final Menu menuArg) {
        this.menu = menuArg;
        MenuInflater inflater = getMenuInflater();
        inflater.inflate(R.menu.options_menu, menu);

        return true;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public boolean onOptionsItemSelected(final MenuItem item) {
        switch (item.getItemId()) {
        case R.id.home:
            showView(VIEW.HOME);
            return true;
        case R.id.param:
            showView(VIEW.SETTINGS);
            return true;
        case R.id.credits:
            showView(VIEW.CREDITS);
            return true;
        default:
            return false;
        }
    }

    /**
     * Method used to display another view(Home, Stats, Settings).
     * 
     * @param viewArg
     *            : the new view to display
     */
    public void showView(final VIEW viewArg) {
        /* Show splash screen */
        showWaitingMessage();

        Class<? extends RootActivity> dest = this.getClass();
        History typeHisto = new History(History.Type.WEEKLY);
        boolean createActitivy = true;
        switch (viewArg) {
        case HOME:
            dest = CigaretteCounter.class;
            break;
        case WEEKLY:
            dest = HistoryActivity.class;
            typeHisto = new History(History.Type.WEEKLY);
            break;
        case MONTHLY:
            dest = HistoryActivity.class;
            typeHisto = new History(History.Type.MONTHLY);
            break;
        case SETTINGS:
            dest = ConfigActivity.class;
            break;
        case CREDITS:
            hideWaitingMessage();
            createActitivy = false;
            new Credits(this);
            break;
        default:
            break;
        }

        if (createActitivy) {
            Intent intent = new Intent(RootActivity.this, dest);
            intent.putExtra(History.class.toString(), typeHisto);
            startActivity(intent);

            if (!(this instanceof CigaretteCounter)) {
                finish();
            }
        }
    }

    @Override
    public void onResume() {
        super.onResume();
        /* Init Ads */
        initAds();

        /* Init Analytics Tracker */
        initTracker();

        Log.d(getLocalClassName(), "onResume");
        db.open();
    }

    @Override
    public void onStart() {
        super.onStart();
        Log.d(getLocalClassName(), "onStart");
        db.open();
    }

    @Override
    public void onRestart() {
        super.onRestart();
        Log.d(getLocalClassName(), "onRestart");
        db.open();

        initTracker();

        /* show splashscreen during complex treatment */
        showWaitingMessage();

        /* Process long/complex treatments in separate thread */
        Thread t = new Thread() {
            @Override
            public void run() {
                /* Init values(from DB, Network, etc.) */
                initValues();

                /* stop this thread and return to the main thread */
                mHandler.post(initValuesComplete);
            }
        };
        t.start();

    }

    @Override
    protected void onDestroy() {
        if (adView != null) {
            adView.destroy();
        }
        super.onDestroy();
        Log.d(getLocalClassName(), "onDestroy");
        hideWaitingMessage();
        GoogleAnalyticsProvider.stopTracker();
    }

    @Override
    protected void onPause() {
        super.onPause();
        Log.d(getLocalClassName(), "onPause");
        hideWaitingMessage();
        // GoogleAnalyticsProvider.stopTracker();
    }

    @Override
    protected void onStop() {
        super.onStop();
        Log.d(getLocalClassName(), "onStop");
    }

    /**
     * @return the Root Context
     */
    public Context getRootContext() {
        Context ctx;
        // Decor View
        ctx = getWindow().getContext();
        // ctx = getWindow().getDecorView().getRootView().getContext();
        // ctx = getWindow().getDecorView().getContext();

        return ctx;
    }

    /**
     * Show a waiting popup.
     */
    public void showWaitingMessage() {
        try {
            Log.d(getLocalClassName(), "show waiting message : " + waitingDialog);
            waitingDialog = new ProgressDialog(getRootContext());
            waitingDialog.setMessage(getResources().getString(R.string.home_waiting));
            waitingDialog.setIndeterminate(true);
            waitingDialog.setCancelable(false);
            waitingDialog.show();
        } catch (IllegalStateException e) {
            try {
                waitingDialog = new ProgressDialog(this);
                waitingDialog.setMessage(getResources().getString(R.string.home_waiting));
                waitingDialog.setIndeterminate(true);
                waitingDialog.setCancelable(false);
                waitingDialog.show();
            } catch (Exception e1) {
                Log.e(getLocalClassName(), "showWaitingMessage 2 : Error : ", e1);
            }
        } catch (Exception e) {
            Log.e(getLocalClassName(), "showWaitingMessage : Error : ", e);
        }
    }

    /**
     * hide the waiting popup.
     */
    public void hideWaitingMessage() {
        try {
            if (waitingDialog != null) {
                Log.d(getLocalClassName(), "dismiss waiting message : " + waitingDialog);
                waitingDialog.dismiss();
                waitingDialog.cancel();
                waitingDialog = null;
            }
        } catch (Exception e) {
            Log.e(getLocalClassName(), "hideWaitingMessage : Error : ", e);
        }
    }

    /**
     * Hide the waiting popup and show a Toast with argument value.
     * 
     * @param id
     *            of the text
     */
    public void hideWaitingMessage(final int id) {
        hideWaitingMessage();
        Toast.makeText(this, id, Toast.LENGTH_SHORT).show();
    }

    /**
     * Hide the 'Waiting' popup and show a Toast.
     * 
     * @param text
     *            to set in the toast
     */
    public void hideWaitingMessage(final String text) {
        hideWaitingMessage();
        Toast.makeText(this, text, Toast.LENGTH_LONG).show();
    }
}
